package infoserver;

import Protocol.*;
import java.net.*;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;


/**
 * Deze klasse wordt gestart zodra een client verbinding maakt met de serversocket
 * Hier worden de aanvragen van de client afgehandeld
 * @author Michael Stevens
 * @since 03-05-2012
 */
public class InfoServerThread implements Runnable{
    private Infoserver is;
    private Socket clientSocket;
    private ComProtocol cp; 
    private int id = 0;
    private BackupManagement bm;
    
    public InfoServerThread(Socket socket, Infoserver is){        
        this.clientSocket = socket;
        this.is = is;  
        bm = new BackupManagement();
       
    }
    
    /**
    * Verwerk een inlog request
    * Geef ok mee bij success en error bij fout
    * @author Michael Stevens
    * @since 04-05-2011
    */
    public void processInloggen(ClientObject co, boolean isMaster){
        id = is.getLogin().excecuteLogin(co.getUsername(), co.getPassword(), isMaster);
            if(id >=1){
                ReturnObject ro = new ReturnObject();
                ro.setMessage(ro.getOk());
                ro.setId(id);
                cp.send(ro);
                is.getGui().writeLog("Gebruiker : " + co.getUsername() + " ingelogd vanaf: " + clientSocket.getInetAddress());
            } else {
                ReturnObject ro = new ReturnObject();
                ro.setMessage(ro.getError());
                cp.send(ro);
            }
    }   
    
    /**    
    * Zet id op 0 en stuur terug dat het gelukt is
    * @author Michael Stevens
    * @since 04-05-2011
    */
    public void processUitloggen(ClientObject co){
        id = 0;
        ReturnObject ro = new ReturnObject();
        ro.setMessage(ro.getOk());
        cp.send(ro);
        is.getGui().writeLog("Gebruiker : " + co.getUsername() + " uitgelogd");
    }    
    
    
    /**
    * Verwerkt een SelectQuery en verstuurt het resultaat 
    * @author Michael Stevens
    * @since 03-05-2011
    */
    private void processSelectQuery(ClientObject co){
        ResultSet rs = is.getSql().excecuteSelectQuery(co.getCommand());
        ReturnObject ro = new ReturnObject();
        is.getGui().writeLog("Gebruiker : " + co.getUsername() + " \n Query : " + co.getCommand());
        try{
            if(rs.next()){
                ro.setMessage(ro.getOk());
                rs.previous();
            }else{                
                ro.setMessage(ro.getError());
            }            
            cp.send(preTransport(rs,ro));
        }catch(Exception e){
            System.out.println(e.getMessage());            
        }
    }
    
    /**
    * Verwerkt een Auth SelectQuery en verstuurt het resultaat 
    * @author Michael Stevens
    * @since 03-05-2011
    */
    private void processAuthSelectQuery(ClientObject co){
        ResultSet rs = is.getSql().excecuteAuthSelectQuery(co.getCommand());
        ReturnObject ro = new ReturnObject();
        is.getGui().writeLog("Gebruiker : " + co.getUsername() + " \n AuthQuery : " + co.getCommand());
        try{
            if(rs.next()){
                ro.setMessage(ro.getOk());
                rs.previous();
            }else{                
                ro.setMessage(ro.getError());
            }            
            cp.send(preTransport(rs,ro));
        }catch(Exception e){
            System.out.println(e.getMessage());            
        }
    }
    
    /**
    * Verwerkt een UpdateQuery en verstuurt het resultaat 
    * @author Michael Stevens
    * @since 03-05-2011
    */
    public void processAuthUpdateQuery(ClientObject co){
       int success = is.getSql().excecuteAuthUpdateQuery(co.getCommand());
       ReturnObject ro = new ReturnObject();
       is.getGui().writeLog("Gebruiker : " + co.getUsername() + " \n AuthQuery : " + co.getCommand());
       if(success == 0){
           ro.setMessage(ro.getError());
       }else{
           ro.setMessage(ro.getOk());
       }
       cp.send(ro);
    }
    
    /**
    * Verwerkt een BackupCreateQuery en verstuurt het resultaat 
    * @author Roman Wiedijk
    * @since 03-06-2011
    */
    public void processBackupCreateQuery(ClientObject co){
        bm.createBackup(co.getCommand());
        
        int success = bm.getSuccess();
        ReturnObject ro = new ReturnObject();
        is.getGui().writeLog("Gebruiker : " + co.getUsername() + " \n BackupCreateQuery : " + co.getCommand());
        if(success == 0){
            ro.setMessage(ro.getError());
        }else{
            ro.setMessage(ro.getOk());
        }
        cp.send(ro);
    }
    
    /**
    * Verwerkt een BackupLoadQuery en verstuurt het resultaat 
    * @author Roman Wiedijk
    * @since 03-06-2011
    */
    public void processBackupLoadQuery(ClientObject co){
        int success = 0;
        int successCounter = bm.loadBackup(co.getCommand(), is);
        if(successCounter == 4){
            success = 1;
        } 
        
        ReturnObject ro = new ReturnObject();
        is.getGui().writeLog("Gebruiker : " + co.getUsername() + " \n BackupLoadQuery : " + co.getCommand());
        if(success == 0){
            ro.setMessage(ro.getError());
        }else{
            ro.setMessage(ro.getOk());
        }
        cp.send(ro);
   }
    
    /**
    * Verwerkt een UpdateBackupList verzoek en verstuurt het resultaat 
    * @author Roman Wiedijk
    * @since 03-06-2011
    */
    public void processUpdateBackupList(ClientObject co){
        bm.refreshElements();
        cp.send(bm.getResults());
        //System.out.println(bm.getResults().toString());
    }
    
    /**
    * Verwerkt een deleteBackup verzoek en verstuurt het resultaat 
    * @author Roman Wiedijk
    * @since 03-06-2011
    */
    public void processDeleteBackup(ClientObject co){
        int success = bm.deleteBackup(co.getCommand());
        System.out.println(co.getCommand());
        
        ReturnObject ro = new ReturnObject();
        if(success == 0){
            ro.setMessage(ro.getError());
        }else{
            ro.setMessage(ro.getOk());
        }
        cp.send(ro);
    }
    
    /**
    * Prepareert een resultaat voor transport door het om te zetten naar een ReturnObject 
    * @author Michael Stevens
    * @since 03-05-2011
    */
     public ReturnObject preTransport(ResultSet rs, ReturnObject ro){ 
        try{
            ResultSetMetaData meta = rs.getMetaData(); // haal meta data op
            
            ArrayList<String> kolom = new ArrayList<String>(); // maak eenmalig een array aan voor de kolom namen
            boolean first = true; // aanduiding voor de eerste iteratie

            while(rs.next()){ // cycle door de rijen van het resultaat
                ArrayList<String> rij = new ArrayList<String>(); // maak voor elke rij een array aan
                for(int i = 0; i < meta.getColumnCount();i++){ // voor het aantal kolommen
                    if(first){// dit wordt alleen in de eerste iteratie uitgevoerd
                        kolom.add(meta.getColumnName(i+1));// schrijf de kolom naam weg naar het array
                    }
                    rij.add(rs.getString(meta.getColumnName(i+1)));// schrijf de kolom data weg naar het array
                }

                if(first){// dit wordt alleen in de eerste iteratie uitgevoerd
                    ro.setColumns(kolom); //plaats het array in het ReturnObject
                }
                first = false; // geef aan dat de eerste iteratie voorbij is
                ro.addRows(rij);// plaats het array in de array van het ReturnObject
            }            
          }catch(SQLException ex){
            System.out.println(ex.getMessage() + "pretrans EX");
          }
        
        return ro;
    } 
    
    
    /**
    * Start het protocol en kijkt om welke actie de client vraagt
    * @author Michael Stevens
    * @since 03-05-2011
    */
    public void run(){
        cp = new ComProtocol(clientSocket);
        
        ClientObject co = (ClientObject) cp.recieve();
        
        if(co.getAction().equals(cp.getInloggen())){
            processInloggen(co, false);
        }else if(co.getAction().equals(cp.getInloggenMaster())){            
            processInloggen(co, true);
        }else{
            id = is.getLogin().excecuteLogin(co.getUsername(), co.getPassword(), false);
        }
        
        if(id >= 1){// kijk of gebruiker is ingelogd
            if(co.getAction().equals(cp.getSelectQuery())){
                processSelectQuery(co);
            }else if(co.getAction().equals(cp.getAuthSelectQuery())){
                processAuthSelectQuery(co);
            }else if(co.getAction().equals(cp.getUpdateQuery())){
                processAuthUpdateQuery(co);
            }else if(co.getAction().equals(cp.getUitloggen())){
                processUitloggen(co);
            }else if(co.getAction().equals(cp.getBackupCreateQuery())){
                processBackupCreateQuery(co);
            }else if(co.getAction().equals(cp.getBackupLoadQuery())){
                processBackupLoadQuery(co);
            }else if(co.getAction().equals(cp.getUpdateBackupList())){
                processUpdateBackupList(co);
            }else if(co.getAction().equals(cp.getDeleteBackup())){
                processDeleteBackup(co);
            }
        }
        cp.close();
     }
        
}   
    


